package com.example.demo.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.example.demo.config.ApiException;
import com.example.demo.config.RetEnum;
import com.example.demo.entity.User;
import com.example.demo.dao.UserDao;
import com.example.demo.service.RedisService;
import com.example.demo.service.UserService;
import com.example.demo.vo.RespInfo;
import com.example.demo.vo.user.LoginParam;
import com.example.demo.vo.user.LoginResp;
import com.example.demo.vo.user.UserInfo;
import com.example.demo.vo.user.UserParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 用户信息表(User)表服务实现类
 *
 * @author yuan
 * @since 2023-01-16 13:57:33
 */
@Service("userService")
@Slf4j
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;
    @Resource
    private RedisService redisService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public RespInfo queryById(Long id) {
        User user = userDao.queryById(id);
        RespInfo<User> respInfo = new RespInfo<>();
        respInfo.setRet(RetEnum.Succeeded);
        respInfo.setData(user);
        return respInfo;
    }


    /**
     * 新增数据
     *
     * @param param 实例对象
     * @return 实例对象
     */
    @Override
    public RespInfo insert(UserParam param, HttpServletRequest request) {
        /**
         * 这里可以获取操作该接口的人的信息，可用于各种操作
         */
        UserInfo userInfo = (UserInfo) request.getAttribute("userInfo");
        if (!userInfo.equals("xxx")) {

        }
        User user = new User();
        user.setStatus(1);
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        user.setUsername(param.getUsername());
        user.setPassword(param.getPassword());
        int num = userDao.insert(user);
        RespInfo respInfo = new RespInfo<>();
        if (num > 0) {
            respInfo.setRet(RetEnum.Succeeded);
        } else {
            respInfo.setRet(RetEnum.Failed);
        }
        return respInfo;
    }

    /**
     * 修改数据
     *
     * @param param 实例对象
     * @return 实例对象
     */
    @Override
    public RespInfo update(UserParam param) {
        User user = userDao.queryById(param.getId());
        user.setUpdateTime(new Date());
        user.setUsername(param.getUsername());
        user.setPassword(param.getPassword());
        user.setStatus(param.getStatus());
        int num = this.userDao.update(user);
        RespInfo respInfo = new RespInfo<>();
        if (num > 0) {
            respInfo.setRet(RetEnum.Succeeded);
        } else {
            respInfo.setRet(RetEnum.Failed);
        }
        return respInfo;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public RespInfo deleteById(Long id) {
        boolean flag = this.userDao.deleteById(id) > 0;
        RespInfo respInfo = new RespInfo<>();
        if (flag) {
            respInfo.setRet(RetEnum.Succeeded);
        } else {
            respInfo.setRet(RetEnum.Failed);
        }
        return respInfo;
    }

    @Override
    public RespInfo login(LoginParam params) {
        User user = new User();
        user.setUsername(params.getUsername());
        User value = this.userDao.queryAll(user);
        RespInfo<LoginResp> respInfo = new RespInfo<>();
        if (value == null) {
            /**
             * 抛出异常或者直接返回都可以（看作用）
             * 1、如果只是弹出错误给用户看，可以直接抛出异常（这种要定义一个全局捕获异常的类，这个项目在GlobalExceptionConfig里面，可以测试下，
             *      调用接口输入不存在的用户，然后在GlobalExceptionConfig的allExceptionHandler中打断点，会发现它调到那边去了）
             * 2、如果该方法返回带着数据可以直接返回（比如成功后返回用户信息），或者需要给另一个方法用
             */
            //            respInfo.setRet(RetEnum.Not_Exit_User);
            //            return respInfo;
            throw new ApiException(RetEnum.Not_Exit_User);
        }
        /**
         * 输入的密码为空或者输入的密码和筛选出来的用户的密码不匹配
         */
        if (StringUtils.isEmpty(params.getPassword()) || !params.getPassword().equals(value.getPassword())) {
//            respInfo.setRet(RetEnum.User_Password_Error);
//            return respInfo;
            throw new ApiException(RetEnum.User_Password_Error);
        }
        /**
         * 随机生成一个token用于通行凭证
         */
        String loginToken = UUID.randomUUID().toString();

        /**
         * 放在redis里面（存储在redis的原因是因为redis基于缓存，速度快，而且有丰富的功能，过期时间设置为一周）
         */
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername(value.getUsername());
        redisService.storeUserInfo(loginToken, userInfo);

        LoginResp loginResp = new LoginResp();
        loginResp.setUsername(value.getUsername());
        loginResp.setLoginToken(loginToken);
        respInfo.setRet(RetEnum.Succeeded);
        respInfo.setData(loginResp);
        return respInfo;
    }

    public RespInfo logout(HttpServletRequest request) {
        String loginToken = request.getHeader("loginToken");
        redisService.delLoginToken(loginToken);
        RespInfo respInfo = new RespInfo<>();
        respInfo.setRet(RetEnum.Succeeded);
        return respInfo;
    }
}
